#include "game.h"

Game::Game ()
{
	generate_objects();	
	generate_map();
}


void Game::generate_map()
{
	_map.setBitmap();
	_map.generate_default_map();
}

void Game::generate_objects()
{
	_digdug = Movables(DIGDUG, game_grid_elements/2, game_grid_elements/2); 
	_monsters.push_back(Movables(MONSTER,  game_grid_elements/2-6, game_grid_elements/2 -10));
	_monsters.push_back(Movables(MONSTER,  game_grid_elements/2-6, game_grid_elements/2 +6));
}

bool Game::update(Action instruction)
{
//Handle Digdug's action first;
//Digdug is always the first object in the vector of movables contained in game
	//Move_result result = HAS_MOVED; 

	if(instruction != SHOOT && instruction != MOVE_NONE)
	{
		//convert enum type instruction to direction
		Direction dir = static_cast<Direction>(instruction);
		_digdug.set_direction(dir);
		if(move(_digdug, dir) == GAME_OVER)
		{return false;} 
	}

	if(instruction == SHOOT)
	{
		//!!projectile code here
	}

//Handle movement of all other movable objects
//start moving through vector containing movable objects of the game starting at the first object after digdug	
	for(int monster_count = 0; monster_count != _monsters.size(); monster_count++)
	{
			Move_result result = HAS_MOVED;
//			do
//			{
//			Direction dir = calculate_direction(_monsters.at(monster_count), _digdug, result);
			Direction dir = UP;
			_digdug.set_direction(dir);
			result = move(_monsters.at(monster_count), dir);
//			}
//			while(result == CANNOT_MOVE);

	}

	return true;
//!!monsters projectile code


}

Rules Game::get_rule(Movable_type object_type, Movable_type map_location_type)
{
	if(map_location_type == HOLE)
	{
		return CAN_MOVE;
	}

	else if(map_location_type == SAND)
	{
		if(object_type == DIGDUG)
		{
			return CAN_MOVE;
		}
		else return CANT_MOVE;
	}

	else if(map_location_type == MONSTER)
	{
		switch(object_type)
		{
		case DIGDUG:
			return DEATH_TO_DIGDUG;
			break;
		case PROJECTILE:
			return DEATH_TO_MONSTER;
			break;
		case MONSTER:
			return CAN_OVERLAP;
			break;
		}
	}
	
	else if(map_location_type == OVERLAP)
	{
		switch(object_type)
		{
		case DIGDUG:
			return DEATH_TO_DIGDUG;
			break;
		case PROJECTILE:
			return DEATH_TO_MONSTER;
			break;
		case MONSTER:
			return CAN_MOVE;
			break;
		}
	}
	

//will only happen if trying to move a monster
	else if(map_location_type == PROJECTILE)
	{
		return DEATH_TO_MONSTER;
	}
	else if(map_location_type == DIGDUG)
	{
		return DEATH_TO_DIGDUG;
	}
	return CAN_MOVE;
}

Move_result Game::move(Movables& movable, Direction direction)
{

	Move_result result = HAS_MOVED;
// get the coordinates and dimensions of the movable
	int start_x = movable.x();
	int start_y = movable.y();
	int x = movable.x(); 
	int y = movable.y();
	int radius = movable.radius();
	int length = 2*radius + 1;
	int speed = movable.speed();


	int delta_x = 0;
	int delta_y = 0;

	switch(direction)
	{
		case UP:	delta_y = -1;	break;
		case DOWN:	delta_y = +1;	break;		
		case LEFT:	delta_x = -1;	break;		
		case RIGHT:	delta_x = +1;	break;
	}

	for (int loop = 1; loop <= speed && result == HAS_MOVED; loop ++)
			{
				x = movable.x(); 
				y = movable.y();
				Map temp_map = _map;

				for (int element = -radius; element <= radius && result == HAS_MOVED; element++)
				{

					int y_check = y + delta_y*(1 + radius) + delta_x*element;
					int x_check = x + delta_x*(1 + radius) + delta_y*element;

					if(x_check < 0 || x_check == game_grid_elements || y_check < 0 || y_check == game_grid_elements)
						result = CANNOT_MOVE;
					else
					{
						switch(get_rule(movable.type(), _map.element(x_check, y_check)))
						{
						case CAN_MOVE:
							_map.set_type(movable.type(), x_check, y_check);
							if (_map.element(x_check - delta_x*length, y_check  - delta_y*length) == OVERLAP)
							_map.set_type(movable.type(), x_check - delta_x*length, y_check -delta_y*length);
							else
							_map.set_type(HOLE, x_check - delta_x*length, y_check - delta_y*length);
							break;
						
						case CANT_MOVE:
							result = CANNOT_MOVE;
							break;
						case DEATH_TO_DIGDUG:
							result = GAME_OVER;
							break;
	//!!must finish writing this case to destroy projectile and specific monster
						case DEATH_TO_MONSTER:
							result = OBJECT_DEAD;
							break;
						case CAN_OVERLAP:
							_map.set_type(OVERLAP, x_check, y_check);
							_map.set_type(HOLE, x_check - delta_x*length, y_check - delta_y*length);			
							break;
						}
					}
					
				}

			if(result == HAS_MOVED)
			{
				movable.set_location(start_x + delta_x, start_y + delta_y);			
			}
			else _map = temp_map;

		}

		if(x == start_x && y == start_y && result != GAME_OVER)
		{
			result = CANNOT_MOVE;
		}
	
		
		return result;
}

Map Game::get_map()
{
	return _map;
}

Movables Game::get_movable (Movable_type type, int vector_count)
{
  switch (type)
  {
	  case DIGDUG:		return _digdug;							break;
	  case MONSTER:		return _monsters.at(vector_count);		break;
	  case PROJECTILE:	return _projectiles.at(vector_count);	break;
	  default:			return _digdug;							break;
	 // case ROCK:		return _rock.at(vector_count);			break;	
  }
}


 Direction Game::calculate_direction(Movables &monster, Movables &digdug, Move_result result) const
 {
	 //Know where we have come from
//	 Direction previous_direction = monster.direction();

	 Direction desired_x_direction = NONE;
	 Direction desired_y_direction = NONE; 

	 int delta_x = monster.x() - digdug.x();
	 int delta_y =  monster.y() - digdug.y();

	

	 //Deterime if we want to go left/right
	 if(delta_x > 0)
		 desired_x_direction = LEFT;
	 else if(delta_x < 0)
		 desired_x_direction = RIGHT;
	
	 //Determine if we want to go up/down
	 if(delta_y > 0)
		 desired_y_direction = UP;
	 else if(delta_y < 0)
		 desired_y_direction = DOWN;

	if(Game::_tracker.empty())
	{
		
	}



 }
